/**
 * requires: 
 * 		onload.js - with method onload.add();
 * 		shield.js - with methods Shield.down(); and Shield.up();
 */

/**
 * Provides procedures to handle, create and elaborate ajax calls.
 * 
 * @param url
 * @param timeout
 * @param postData - JS object or null
 * @param load - function(response)
 * @param error - function(response)
 * @param timeoutHandler - function()
 * 
 * @throws Exception when postData couldn't be strigified
 * @return
 */
function Ajax(url, timeout, postData, loadHandler, errorHandler, timeoutHandler) {
	this.xhr = Ajax.xmlHttpObject();
	this.xhr.open("POST", url, true);
	this.xhr.onreadystatechange = function() {
		if (this.readyState == 4) {
			try {
				console.log("Ajax response received.");
				console.log(this.responseText);
				clearTimeout(this.parent.xhrTimeout);
				if (this.status == 200) {
					loadHandler(this.responseText);
				} else if (this.status >= 400 && this.status <= 505) {
					if (this.status == 404) {
						console.error ("Requested URL is not found.");
					} else if (this.status == 403) {
						console.error("Access denied.");
					}
					errorHandler(this.responseText);
				} else {
					console.log("status is " + this.status);
				}
			} catch(e) {
				console.error("Exception in ajax response handler: " + e);
			} finally {
				Shield.down();
			}
		}
	};
	this.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	//xhr.setRequestHeader("Content-length", parameters.length);
	this.xhr.setRequestHeader("Connection", "close");
	if (typeof postData != "undefined" && postData != null) {
		this.postData = "ajaj=" + JSON.stringify(postData);
	}
	this.timeout = timeout;
	this.xhrTimeout = null;
	this.timeoutHandler = timeoutHandler;
	
	return this;
}

/**
 * Create ajax object according to browser's needs.
 * @return ajax object
 */
Ajax.xmlHttpObject = function() {
	try {
		// Firefox, Opera 8.0+, Safari
		return new XMLHttpRequest();
	} catch (e) {
		// Internet Explorer
		var progIds = new Array("Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0",
				"Msxml2.XMLHTTP.4.0", "Msxml2.XMLHTTP.3.0", "Msxml2.XMLHTTP",
				"Microsoft.XMLHTTP");
		for (i in progIds) {
			try {
				return new ActiveXObject(progIds[i]);
			} catch (ex) {
				console.error(progIds[i]);
			}
		}
	}
	return null;
};

/**
 * This is called when timeout for ajax call exceeds.
 * 
 * @param id - identification of a call.
 */
Ajax.timeoutHandler = function (id) {
	console.log("in timeoutHandler");
	var xho = Ajax.registry.splice(id, 1, null)[0];
	xho.xhr.abort();
	xho.timeoutHandler();
};

/**
 * Internal structure for calls done.
 */
Ajax.registry = [];

/**
 * Send request to the server.
 * 
 * @param shieldMsg - message to show in Shield
 * @return
 */
Ajax.prototype.sendRequest = function(shieldMsg) {
	try {
		Shield.up(typeof (shieldMsg) != "string" || shieldMsg == null ? "" : shieldMsg);
		
		var id = 0;
		for (; id < Ajax.registry.length; ++id) {
			if (Ajax.registry[id] == null) {
				Ajax.registry[id] = this;
				continue;
			}
		}
		if (id == Ajax.registry.length) {
			Ajax.registry[id] = this;
		}
		
		this.xhr.parent = this;
		this.xhrTimeout = setTimeout("Ajax.timeoutHandler(" + id + ");", this.timeout);
		this.xhr.send(this.postData);
	} catch (e) {
		console.error('exception in sendRequest: ' + e);
	}
};

/**
 * Class constructor
 * instances of this object are used when sending a data to the server.
 * 
 * @param data - data to send
 * @param action - action to trigger on the server
 */
function AjaxDeliveryBoy (data, action) {
	this.data = data;
	this.action = action;
	return this;
}

/**
 * Create standart ajax call used in EAIIS
 * 
 * @param url
 * @param data
 * @param callback - when successfull
 * @return - ajax object
 */
Ajax.createStdCall = function(url, data, callback) {
	try {
		errormsg.hideBox("offer-list-ajax-error");
		errormsg.hideBox("offer-list-ajax-timeout");
		var ajaxCall = new Ajax(url, 5000, data, function(response) {
			var errormsg = Errormsg.getErrormsg();
			errormsg.hideBox("offer-list-ajax-error");
			errormsg.hideBox("offer-list-ajax-timeout");
			if (callback != null) {
				callback(response);
			}
		}, function(response) {
			var errormsg = Errormsg.getErrormsg();
			if (response != null && response != "") {
				errormsg.addError(response, "offer-list-ajax-error");
			} else {
				errormsg.addError("Problem occured when connecting to the server. Please contact administrator.", "offer-list-ajax-error");
			}
		}, function() {
			var errormsg = Errormsg.getErrormsg();
			errormsg.addError("Server request timed out.  Did you lose network connectivity for some reason?", "offer-list-ajax-timeout");
		});
		return ajaxCall;
	} catch (e) {
		console.error(e);
		throw e;
	}
	
};


/**
 * Send ids to the server
 * 
 * @param inputIdPrefix
 * @param arr
 * @param action
 * @param msg
 * @param callback
 * @return
 */
Ajax.sendIds = function(inputIdPrefix, arr, action, msg, callback) {
	var arrOfIds = [];
	for (var index in arr) {
		arrOfIds.push(arr[index].value.replace(new RegExp("^"+inputIdPrefix+"-", "g"), ""));
	}
	if (arrOfIds.length <= 0) {
		return;
	}
	var ajaxCall = Ajax.createStdCall("index.php?a=a", new AjaxDeliveryBoy(arrOfIds, action), callback);
	ajaxCall.sendRequest(msg);
};

/**
 * Get checkbox which are selected in a container
 * 
 * @param containerId
 * @param inputIdPrefix
 * @return array of selected inputs
 */
Ajax.getSelectedInputs = function(containerId, inputIdPrefix) {
	var offerList = document.getElementById(containerId);
	var inputsAll = offerList.getElementsByTagName("input");
	var selectedInputs = [];
	var offerInputRegExp = new RegExp("^"+inputIdPrefix+"-[0-9][0-9]*$");
	for (var index in inputsAll) {
		var input = inputsAll[index];
		if (input.type == "checkbox" && input.checked == true && offerInputRegExp.test(input.value)) {
			selectedInputs.push(input);
		}
	}
	return selectedInputs;
};

/**
 * Used when adding offers to interested in box.
 * 
 * @param elem
 * @param containerId
 * @param inputIdPrefix
 * @return
 */
Ajax.getIdsForSelectedOffersAndAdd = function(elem, containerId, inputIdPrefix) {
	var arr = Ajax.getSelectedInputs(containerId, inputIdPrefix);
	Ajax.sendIds(inputIdPrefix, arr, "addOffersToII", "Adding selected offers to 'Interested In Box'.");
};

/**
 * Used when removing offers from the interested box.
 * 
 * @param elem
 * @param containerId
 * @param inputIdPrefix
 * @return
 */
Ajax.getIdsForSelectedOffersAndRemove = function(elem, containerId, inputIdPrefix) {
	var arr = Ajax.getSelectedInputs(containerId, inputIdPrefix);
	Ajax.sendIds(inputIdPrefix, arr, "removeOffersFromII", "Removing selected offers from 'Interested In Box'.", function() {
		Common.refreshPage();
	});
};

Ajax.getIdsForSelectedOffersAndAddInListView = function(elem) {
	Ajax.getIdsForSelectedOffersAndAdd(elem, "offer-list", "offer");
};
Ajax.getIdsForSelectedOffersAndRemoveInListView = function(elem) {
	Ajax.getIdsForSelectedOffersAndRemove(elem, "offer-list", "offer");
};
Ajax.getIdsForSelectedOffersAndAddInThumbView = function(elem) {
	Ajax.getIdsForSelectedOffersAndAdd(elem, "offer-thumb-container", "offer");
};
Ajax.getIdsForSelectedOffersAndRemoveInThumbView = function(elem) {
	Ajax.getIdsForSelectedOffersAndRemove(elem, "offer-thumb-container", "offer");
};
Ajax.getIdsForSelectedOffersAndAddInBothViews = function() {
	var arr = Ajax.getSelectedInputs("container", "offer");
	Ajax.sendIds("offer", arr, "addOffersToII", "Adding selected offers to 'Interested In Box'.");
};
Ajax.getIdsForSelectedOffersAndDelete = function(elem) {
	var arr = Ajax.getSelectedInputs("offer-list", "offer");
	Ajax.sendIds("offer", arr, "deleteOffers", "Deleting selected offers from the database.", function() {
		Common.refreshPage();
	});
};
Ajax.getIdsForSelectedOffersAndHide = function(elem) {
	var arr = Ajax.getSelectedInputs("offer-list", "offer");
	Ajax.sendIds("offer", arr, "hideOffers", "Hiding selected offers in the database.", function() {
		//Common.refreshPage(); TODO remove this comment
	});
};
Ajax.getIdsForSelectedUsersAndDelete = function(elem) {
	var arr = Ajax.getSelectedInputs("offer-list", "user");
	Ajax.sendIds("user", arr, "deleteUsers", "Deleting selected users from the database.", function() {
		Common.refreshPage();
	});
};
// TODO move this to another file
/**
 * 
 * @param value
 * @param view - "Thumb" or "List"
 * @return
 */
Ajax.setCountOfPagesForView = function(value, view) {
	var ajaxCall = Ajax.createStdCall("index.php?a=a", new AjaxDeliveryBoy(value, "setCountOfPagesFor"+view+"View"), function() {
		Common.refreshPage();
	});
	ajaxCall.sendRequest("Setting default count of pages for this view.");
};

Ajax.setCountOfPagesForListView = function(value) {
	Ajax.setCountOfPagesForView(value, "List");
};
Ajax.setCountOfPagesForThumbView = function(value) {
	Ajax.setCountOfPagesForView(value, "Thumb");
};
